package the.broccoli.uc.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.wisteria.framework.web.mvc.constant.WebConsts;
import org.wisteria.framework.web.mvc.service.AbstractSuperService;
import the.broccoli.ac.constant.ResType;
import the.broccoli.ac.dto.ResCondition;
import the.broccoli.ac.dto.ResDTO;
import the.broccoli.ac.dto.ResTree;
import the.broccoli.ac.entity.Res;
import the.broccoli.ac.service.IResService;
import the.broccoli.uc.entity.RoleRes;
import the.broccoli.uc.mapper.RoleResMapper;
import the.broccoli.uc.service.IRoleResService;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 角色与资源 服务实现类
 * </p>
 *
 */
@Service
public class RoleResServiceImpl extends AbstractSuperService<RoleResMapper, RoleRes> implements IRoleResService {

    @Autowired
    private IResService resService;

    /**
     * 获取已关联的资源ID
     * @param roleId
     * @return
     */
    @Override
    public List<String> getResIdList(String roleId) {
        return baseMapper.selectResIdList(Arrays.asList(roleId));
    }

    /**
     * 根据角色ID获取关联的资源；树形结构
     *
     * @param roleId
     * @return
     */
    @Override
    public List<ResDTO> getResList(String roleId) {
        return getResList(Arrays.asList(roleId));
    }

    /**
     * 根据角色ID获取关联的资源；树形结构
     * @param roleIdList
     * @return
     */
    @Override
    public List<ResDTO> getResList(List<String> roleIdList) {
        ResCondition condition = new ResCondition();
        condition.setResIdList(baseMapper.selectResIdList(roleIdList));
        List<Res> resList = resService.listByCondition(condition);

        List<ResDTO> data = new ArrayList<>();
        if (!CollectionUtils.isEmpty(resList)) {
            ResDTO dto = null;
            for (Res res : resList) {
                if (WebConsts.ROOT.equals(res.getParentId())) {
                    dto = new ResDTO();
                    dto.setResId(res.getResId());
                    dto.setTitle(res.getResName());
                    dto.setHref(res.getUrl());
                    data.add(dto);
                }
            }

            for (ResDTO d : data) {
                setChildren(d, resList);
            }
        }
        return data;
    }

    /**
     * 获取资源树
     * @param roleId    角色ID
     * @return
     */
    @Override
    public List<ResTree> getResTree(String roleId) {
        return getResTree(Arrays.asList(roleId), null);
    }

    /**
     * 获取资源树
     * @param roleIdList    角色ID列表
     * @param resTypeList   资源类型列表
     * @return
     */
    @Override
    public List<ResTree> getResTree(List<String> roleIdList, List<ResType> resTypeList) {
        return resService.getTree(baseMapper.selectResIdList(roleIdList), resTypeList);
    }

    /**
     * 获取资源列表
     * @param resType   资源类型
     * @return
     */
    @Override
    public List<Res> getResList(ResType resType) {
        return getResList(null, resType);
    }

    /**
     * 获取资源列表
     * @param roleIdList    角色ID列表
     * @param resType       角色类型
     * @return
     */
    @Override
    public List<Res> getResList(List<String> roleIdList, ResType resType) {
        ResCondition condition = new ResCondition();
        if (!CollectionUtils.isEmpty(roleIdList)) {
            condition.setResIdList(baseMapper.selectResIdList(roleIdList));
        }
        condition.setResTypeList(Arrays.asList(resType.getValue()));
        return resService.listByCondition(condition);
    }

    /**
     * 设置子级
     */
    private void setChildren(ResDTO dto, List<Res> resList) {
        for (Res res : resList) {
            if (dto.getResId().equals(res.getParentId())) {
                ResDTO rDTO = null;
                if (dto.getChilds() == null) {
                    dto.setChilds(new ArrayList<>());
                }
                rDTO = new ResDTO();
                rDTO.setResId(res.getResId());
                rDTO.setTitle(res.getResName());
                rDTO.setHref(res.getUrl());
                dto.getChilds().add(rDTO);

                setChildren(rDTO, resList);
            }
        }
    }

    @Transactional
    @Override
    public void save(String roleId, List<String> resIdList, String createdId, String createdName) {
        baseMapper.deleteByRoleId(roleId, createdId, createdName, new Date());

        if (!CollectionUtils.isEmpty(resIdList)) {
            List<RoleRes> entityList = new ArrayList<>();
            RoleRes entity = null;
            for (String resId : resIdList) {
                if (!StringUtils.hasText(resId)) {
                    continue;
                }

                entity = new RoleRes();
                entity.setRoleId(roleId);
                entity.setResId(resId);
                entity.setCreatedId(createdId);
                entity.setCreatedName(createdName);
                entity.setCreatedTime(new Date());
                entityList.add(entity);
            }
            saveBatch(entityList);
        }
    }

    /**
     * 删除角色的应用资源
     * @param roleId    角色ID
     * @param appId     应用ID
     * @return  执行结果
     */
    @Override
    public boolean removeAppResOfRole(String roleId, Integer appId) {
        return this.baseMapper.update(null, new LambdaUpdateWrapper<RoleRes>()
                .set(RoleRes::getIsDeleted, 1)
                .set(RoleRes::getModifiedTime, new Date())

                .eq(RoleRes::getRoleId, roleId)
                .eq(RoleRes::getAppId, appId)
        ) > 0;
    }

}
